package cn.com.ry.framework.linklog.httpclient.filter;

import cn.com.ry.framework.linklog.constant.LinkLogConstants;
import cn.com.ry.framework.linklog.context.LinkLogContext;
import cn.com.ry.framework.linklog.context.SpanIdGenerator;
import cn.com.ry.framework.linklog.util.HostInfo;
import cn.com.ry.framework.linklog.util.LinkLogPrintUtil;
import cn.com.ry.framework.linklog.util.LinkLogSwitch;
import org.apache.http.*;
import org.apache.http.protocol.HttpContext;
import org.apache.http.protocol.HttpCoreContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * HttpClient 拦截器
 */
public class LinkLogHttpRequestInterceptor implements HttpRequestInterceptor {
    private static final Logger logger = LoggerFactory.getLogger(LinkLogHttpRequestInterceptor.class);

    @Override
    public void process(HttpRequest httpRequest, HttpContext httpContext) {
        //1.判断上下文有没有 traceId
        //springboot该方法有个bug
        String traceId = LinkLogContext.getTraceId();
        if (traceId != null && !traceId.equals("")) {
            String preApp = HostInfo.getAppName();
            String preHost = HostInfo.getHostName();
            String preIp = HostInfo.getIp();
            String spanId = SpanIdGenerator.generateNextSpanId();
            httpRequest.addHeader(LinkLogConstants.LINKLOG_PRE_APP_KEY, preApp);
            httpRequest.addHeader(LinkLogConstants.LINKLOG_PRE_HOST_KEY, preHost);
            httpRequest.addHeader(LinkLogConstants.LINKLOG_PRE_IP_KEY, preIp);
            httpRequest.addHeader(LinkLogConstants.LINKLOG_TRACE_KEY, traceId);
            httpRequest.addHeader(LinkLogConstants.LINKLOG_SPANID_KEY, spanId);
            //记录请求日志
            if (LinkLogSwitch.ACCESSLOG) {
                buildAccessLog(httpRequest, httpContext);
            }
        } else {
            logger.debug("[LinkLog]本地threadLocal变量没有正确传递traceId,本次调用不传递traceId");
        }
    }

    public void buildAccessLog(HttpRequest httpRequest, HttpContext httpContext) {
        String requestURI = "";
        String requestURLStr = "";
        String method = "";
        String queryString = "";
        String userAgent = "";
        String forwarded = "";
        if (httpRequest instanceof HttpEntityEnclosingRequest) {
            HttpEntity entity = ((HttpEntityEnclosingRequest) httpRequest).getEntity();
            if (entity != null) {
                InputStream inputStream = null;
                InputStreamReader inputStreamReader = null;
                BufferedReader bufferedReader = null;
                try {
                    inputStream = entity.getContent();
                    inputStreamReader = new InputStreamReader(inputStream);
                    bufferedReader = new BufferedReader(inputStreamReader);
                    queryString = bufferedReader.lines().collect(Collectors.joining("\n"));
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    if (bufferedReader != null) {
                        try {
                            bufferedReader.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                    if (inputStreamReader != null) {
                        try {
                            inputStreamReader.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                    if (inputStream != null) {
                        try {
                            inputStream.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
        Header userAgentHeader = httpRequest.getFirstHeader("User-Agent");
        if (userAgentHeader != null) {
            userAgent = userAgentHeader.getValue();
        }
        Header xForwardedFor = httpRequest.getFirstHeader("X-Forwarded-For");
        if (xForwardedFor != null) {
            forwarded = xForwardedFor.getValue();
        }
        RequestLine requestLine = httpRequest.getRequestLine();
        if (requestLine != null) {
            requestURI = httpRequest.getRequestLine().getUri();
            method = httpRequest.getRequestLine().getMethod();
        }

        HttpCoreContext httpCoreContext = HttpCoreContext.adapt(httpContext);
        if (httpCoreContext != null && httpCoreContext.getTargetHost() != null) {
            requestURLStr = httpCoreContext.getTargetHost().toString() + requestURI;
        }

        Map map = new HashMap();
        map.put("linkLogAccessType", LinkLogConstants.LINKLOG_LOG_CLIENT);
        map.put("requestURI", requestURI);
        map.put("requestURLStr", requestURLStr);
        map.put("method", method);
        map.put("userAgent", userAgent);
        map.put("forwarded", forwarded);
        LinkLogPrintUtil.printRequestLog(queryString, LinkLogHttpRequestInterceptor.class.getName(), map);
    }

}
